import math
import random

import cv2
import cvzone
from cvzone.HandTrackingModule import HandDetector
import numpy as np
import mediapipe as mp

cap = cv2.VideoCapture(0)
cap.set(3, 1280)
cap.set(4, 720)

dector = HandDetector(detectionCon=0.8, maxHands=1)  # 置信度为0.8，最大的手的数量是1


class snakegun:
    def __init__(self):
        self.points = []  # 所有点的位置
        self.length = []  # 两点之间的长度
        self.currentlength = 0  # 蛇的总长度
        self.allowedlength = 150  # 允许长度
        self.privioushead = 0, 0  # 过去的头部点

        self.foodPoint = 0, 0
        self.randomFoodLocation()

        self.score = 0
        self.gameover=False

    def randomFoodLocation(self):
        self.foodPoint = random.randint(100, 1000), random.randint(100, 600)

    def update(self, imgmain, currentHead):
        if(self.gameover):
            cvzone.putTextRect(imgmain,"Game Over",[300,400],scale=7,thickness=5,offset=20)
            cvzone.putTextRect(imgmain, f"Your score is {self.score}", [300, 400], scale=7, thickness=5, offset=20)
        else:
            px, py = self.privioushead
            cx, cy = currentHead

            self.points.append([cx, cy])
            distance = math.hypot(cx - px, cy - py)
            self.length.append(distance)
            self.currentlength += distance
            self.privioushead = cx, cy

            # reducelength_gun
            if (self.currentlength > self.allowedlength):
                for i, length in enumerate(self.length):
                    self.currentlength -= length
                    self.length.pop(i)  # pop  删除 列表中某一个元素（并返回值）
                    self.points.pop(i)

                    if (self.currentlength < self.allowedlength):
                        break

            # snake ate the food
            rx, ry = self.foodPoint
            if (rx - 20 < cx < rx + 20 and ry - 20 < cy < ry + 20):
                print("ate")
                self.randomFoodLocation()
                self.allowedlength += 50
                self.score += 1

            # draw snake
            if self.points:
                for i, point in enumerate(self.points):
                    if i != 0:
                        cv2.line(imgmain, self.points[i - 1], self.points[i], (0, 0, 255), 20)
                cv2.circle(img, self.points[-1], 20, (200, 0, 200), cv2.FILLED)  # 在手指所在的上一个位置画出一个大圆

            # draw food

            imgmain = cv2.circle(img, (rx, ry), 20, (165, 200, 100), cv2.FILLED)  # 在手指所在的上一个位置画出一个大圆
            cvzone.putTextRect(imgmain, f"score : {self.score}", [50, 80], scale=3, thickness=3, offset=10)

            # check the collisions
            pts = np.array(self.points[:-2], np.int32)
            pts = pts.reshape((-1, 1, 2))
            cv2.polylines(imgmain, [pts], False, (0, 200, 0), 3)
            min_dis = cv2.pointPolygonTest(pts, (cx, cy), True)

            if (-1 <= min_dis <= 1):
                self.gameover = True
                self.points = []  # 所有点的位置
                self.length = []  # 两点之间的长度
                self.currentlength = 0  # 蛇的总长度
                self.allowedlength = 150  # 允许长度
                self.privioushead = 0, 0  # 过去的头部点
                self.randomFoodLocation()
        return imgmain


game = snakegun()

while True:
    success, img = cap.read()
    img = cv2.flip(img, 1)
    hands, img = dector.findHands(img, flipType=False)  # 在视频中找到手，并确定镜像翻转模式

    if hands:
        lmlist = hands[0]['lmList']  # 找出手所在的所有关节点的坐标
        pointindex = lmlist[8][0:2]  # 找出手所在的特定关节点的坐标
        img = game.update(img, pointindex)

        # cv2.circle(img,pointindex,20,(200,0,200),cv2.FILLED)  #在手指所在的位置画出一个大圆

    cv2.imshow("img", img)
    key=cv2.waitKey(1)
    if key==ord('r'):
        game.gameover=False
